/*** Created Time: 2022年5月24日 17:00:48 ***/
/*** Author: Eric                        ***/

// 从用户态可直接执行系统调用相关的程序

#include <onix/syscall.h>
#include <onix/types.h>

// _syscall0表示没有输入参数的系统调用
static _inline u32 _syscall0(u32 nr)
{
    u32 ret;
    // 输入：将nr变量写入eax寄存器
    // 汇编代码：int 0x80
    // 输出：将eax寄存器写入ret变量中
    __asm__ __volatile__(
        "int $0x80\n"
        : "=a"(ret)
        : "a"(nr)
    );

    return ret;
}

// _syscall1表示有一个输入参数的系统调用
static _inline u32 _syscall1(u32 nr, u32 arg)
{
    u32 ret;
    // 输入：将nr变量写入eax寄存器，将第一个参数arg写入ebx寄存器
    // 汇编代码：int 0x80
    // 输出：将eax寄存器写入ret变量中
    __asm__ __volatile__(
        "int $0x80\n"
        : "=a"(ret)
        : "a"(nr), "b"(arg)
    );

    return ret;
}

//  _syscall2表示有两个输入参数的系统调用
static _inline u32 _syscall2(u32 nr, u32 arg1, u32 arg2)
{
    u32 ret;
    asm volatile(
        "int $0x80\n"
        : "=a"(ret)
        : "a"(nr), "b"(arg1), "c"(arg2));
    return ret;
}

//  _syscall3表示有三个输入参数的系统调用
static _inline u32 _syscall3(u32 nr, u32 arg1, u32 arg2, u32 arg3)
{
    u32 ret;
    asm volatile(
        "int $0x80\n"
        : "=a"(ret)
        : "a"(nr), "b"(arg1), "c"(arg2), "d"(arg3));
    return ret;
}

u32 test(void)
{
    return _syscall0(SYS_NR_TEST);
}

// exit 系统调用函数
void exit(int status)
{
    _syscall1(SYS_NR_EXIT, (u32)status);
}

// fork 系统调用函数
pid_t fork(void)
{
    return _syscall0(SYS_NR_FORK);
}

// waitpid 系统调用函数
pid_t waitpid(pid_t pid, int32 *status)
{
    return _syscall2(SYS_NR_WAITPID, pid, (u32)status);
}

// yield系统调用函数
void yield(void)
{
    _syscall0(SYS_NR_YIELD);
}

// 睡眠系统调用函数
void sleep(u32 ms)
{
    _syscall1(SYS_NR_SLEEP, ms);
}

// getpid 系统调用函数
pid_t getpid(void)
{
    return _syscall0(SYS_NR_GETPID);
}

// getppid 系统调用函数
pid_t getppid(void)
{
    return _syscall0(SYS_NR_GETPPID);
}

// brk 系统调用
int32 brk(void *addr)
{
    return _syscall1(SYS_NR_BRK, (u32)addr);
}

// write 系统调用
int32 write(fd_t fd, char *buf, u32 len)
{
    return _syscall3(SYS_NR_WRITE, fd, (u32)buf, len);
}

// time 系统调用
time_t time(void)
{
    return _syscall0(SYS_NR_TIME);
}
